/****
	Copyright 2011 Taras Kulbachka

	Licensed under the Apache License, Version 2.0 (the "License");
	you may not use this file except in compliance with the License.
	You may obtain a copy of the License at

		http://www.apache.org/licenses/LICENSE-2.0

	Unless required by applicable law or agreed to in writing, software
	distributed under the License is distributed on an "AS IS" BASIS,
	WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
	See the License for the specific language governing permissions and
	limitations under the License.
*/
package com.atdevsoft.apps.abyss;

import android.app.AlertDialog;
import android.app.ListActivity;
import android.content.ContentValues;
import android.content.Context;
import android.content.DialogInterface;
import android.content.Intent;
import android.content.SharedPreferences;
import android.database.Cursor;
import android.database.sqlite.SQLiteDatabase;
import android.graphics.Rect;
import android.os.Bundle;
import android.preference.PreferenceManager;
import android.text.ClipboardManager;
import android.text.Html;
import android.util.Log;
import android.view.Menu;
import android.view.MenuInflater;
import android.view.MenuItem;
import android.view.View;
import android.view.View.OnClickListener;
import android.view.View.OnLongClickListener;
import android.widget.AdapterView;
import android.widget.ArrayAdapter;
import android.widget.ImageButton;
import android.widget.TextView;
import android.widget.Toast;
import android.widget.AdapterView.OnItemClickListener;
import android.widget.AdapterView.OnItemLongClickListener;

public class QuotesActivity extends ListActivity {
	public static final int QUOTES_PER_PAGE = 30;
	//public static final float AVG_QUOTES_PER_BASH_PAGE = 53.91319f;
	
	public static final String LAST_VISIBLE_SUFFIX_ABYSS_BEST = "";
	public static final String LAST_VISIBLE_SUFFIX_FAVORITES = "-favs";	
	
	private SQLiteDatabase mDb;	
	
	private int mCurrentFirstQuote;
	private int mCurrentQuotesOnPage;
	private int mCurrentLastQuote;
	private int mCurrentPage;
	private int mTotalPages;	
	
	private ImageButton mBtnPrev;
	private ImageButton mBtnNext;	
	private TextView mTvCurrPage;
	private TextView mTvTitle;		
	
	private SharedPreferences mPreferences;
	private Context mContext;
	
	private String mCurrentQuotesTable = "";
	private String mCurrentLastVisibleSuffix = LAST_VISIBLE_SUFFIX_ABYSS_BEST;	

    private int getTotalPages() {
        Cursor getTotPage = mDb.rawQuery("select count(*) from " + mCurrentQuotesTable, null);
        getTotPage.moveToFirst();     
        int pages = (int)Math.ceil((double)getTotPage.getInt(0)/QUOTES_PER_PAGE);
        getTotPage.close();
    	return pages;
    }
    
    private void setPage(int topQuote, int bottomQuote, boolean exactly) {
    	int quotesPerPage = QUOTES_PER_PAGE + 1;
    	if (exactly)
    		quotesPerPage = QUOTES_PER_PAGE;
    	String query;
    	if ((topQuote == 0) && (bottomQuote == 0)) // set quotes from the first (max id) we have
    		query = "select " + DatabaseHelper.QUOTES_ID + ", " + DatabaseHelper.QUOTES_SOURCE_ID + ", " +
    				DatabaseHelper.QUOTES_POSTED + ", " + DatabaseHelper.QUOTES_QUOTE + 
    				" from " + mCurrentQuotesTable + 
    				" order by 2 desc limit 0, " + String.valueOf(quotesPerPage);
    	else if (topQuote != 0) // set quotes starting from the topQuote and QUOTES_PER_PAGE + 1 count
    		query = "select " + DatabaseHelper.QUOTES_ID + ", " + DatabaseHelper.QUOTES_SOURCE_ID + ", " +
    				DatabaseHelper.QUOTES_POSTED + ", " + DatabaseHelper.QUOTES_QUOTE + 
    				" from " + mCurrentQuotesTable + 
    				" where " + DatabaseHelper.QUOTES_SOURCE_ID + " <= " + String.valueOf(topQuote) +
    				" order by 2 desc limit 0, " + String.valueOf(quotesPerPage);    	
    	else  // set quotes starting from the bottomQuote - QUOTES_PER_PAGE
    		  // BUT! if there are less quotes than bottomQuote - QUOTES_PER_PAGE in DB, we need to add more of them coming after bottomQuote
    		  // to have next button. Union is used for that part
    		  // we also have nested select here becuase we need to have set of quotes limited from the bottom of the sort order
    		query = "select " + DatabaseHelper.QUOTES_ID + ", " + DatabaseHelper.QUOTES_SOURCE_ID + ", " +
    				DatabaseHelper.QUOTES_POSTED + ", " + DatabaseHelper.QUOTES_QUOTE + 
    				" from " + mCurrentQuotesTable + 
    				" where " + DatabaseHelper.QUOTES_SOURCE_ID + " in " +
    				"(select " + DatabaseHelper.QUOTES_SOURCE_ID + " from " + mCurrentQuotesTable +
    				" where " + DatabaseHelper.QUOTES_SOURCE_ID + " >= " + String.valueOf(bottomQuote) + 
    				" order by 1 asc limit 0, " + String.valueOf(quotesPerPage) + ") " +
    				"union select " + DatabaseHelper.QUOTES_ID + ", " + DatabaseHelper.QUOTES_SOURCE_ID + ", " +
    				DatabaseHelper.QUOTES_POSTED + ", " + DatabaseHelper.QUOTES_QUOTE + 
    				" from " + mCurrentQuotesTable + 
    				" where " + DatabaseHelper.QUOTES_SOURCE_ID + " < " + String.valueOf(bottomQuote) +
    				" order by 2 desc limit 0, " + String.valueOf(quotesPerPage);
    	    	
    	
    	
        Cursor cursor = mDb.rawQuery(query, null);
        if (cursor.getCount() <= 0) {
            mTvCurrPage.setText(String.format(getString(R.string.pages_template), 0, 0, 0));        	
            setListAdapter(null);
            //.getListView().setAdapter(null);
        	//QuoteAdapter adapter = (QuoteAdapter)getListAdapter();        	
        	//adapter.changeCursor(null);
        	//adapter.Count = 0;		        	
        	cursor.close();
        	return;
        }
        
        cursor.moveToLast();        
        mCurrentLastQuote = cursor.getInt(cursor.getColumnIndex(DatabaseHelper.QUOTES_SOURCE_ID));
        cursor.moveToFirst();
        mCurrentFirstQuote = cursor.getInt(cursor.getColumnIndex(DatabaseHelper.QUOTES_SOURCE_ID));
        
        mCurrentQuotesOnPage = cursor.getCount();
        
        Cursor getCurrPage = mDb.rawQuery("select count(*) from " + mCurrentQuotesTable + " where " + 
        		DatabaseHelper.QUOTES_SOURCE_ID + " > " + String.valueOf(mCurrentFirstQuote), null);
        getCurrPage.moveToFirst();        
        mCurrentPage = (int)Math.ceil((double)getCurrPage.getInt(0)/QUOTES_PER_PAGE) + 1;
        getCurrPage.close();
        
        if (mTotalPages < 0)
        	mTotalPages = getTotalPages();
        if (mCurrentPage > mTotalPages) // because we may start from the middle of the page, mCurrentPage > mTotalPages is real but strange for user
        	mCurrentPage = mTotalPages;
        
        int cqop = mCurrentQuotesOnPage;
        if (mCurrentQuotesOnPage > QUOTES_PER_PAGE)
        	cqop = QUOTES_PER_PAGE;
        mTvCurrPage.setText(String.format(getString(R.string.pages_template), mCurrentPage, mTotalPages, cqop));

        
        Log.d("abyss", String.valueOf(mCurrentQuotesOnPage));
        if (getListAdapter() != null) {
        	QuoteAdapter adapter = (QuoteAdapter)getListAdapter();
        	adapter.changeCursor(cursor);
        	adapter.Count = mCurrentQuotesOnPage;
		        	
        	getListView().setSelectionAfterHeaderView();
        } else {	        
	        try {
	        	QuoteAdapter adapter = new QuoteAdapter(this, R.layout.quote, cursor,
	        			new String[] { DatabaseHelper.QUOTES_ID }, new int[] { android.R.id.text1 });
	
	        	setListAdapter(adapter);

	        } catch (Exception e) {
	        	e.printStackTrace();
	        } 		    	
        }        

    }
    
    private void setQuotesTable(String newTable, Bundle savedInstanceState) {
    	if (!mCurrentQuotesTable.equals("")) {
    		saveTopVisible();
    	}
    	
    	mCurrentQuotesTable = newTable;
    	mCurrentLastVisibleSuffix = "";
    	if (newTable.equals(DatabaseHelper.TABLE_NAME_ABYSSBESTQUOTES)) {
    		mCurrentLastVisibleSuffix = LAST_VISIBLE_SUFFIX_ABYSS_BEST;
    		mTvTitle.setText(getString(R.string.title_abyssbest));
    		
    	} else if (newTable.equals(DatabaseHelper.TABLE_NAME_FAVORITES)) {
    		mCurrentLastVisibleSuffix = LAST_VISIBLE_SUFFIX_FAVORITES;
    		mTvTitle.setText(getString(R.string.title_favs));
    	} else {
    		mTvTitle.setText("");
    	}
    	
        mCurrentFirstQuote = -1;
        mCurrentPage = -1;
        mCurrentQuotesOnPage = -1;  
        mTotalPages = -1;
        
        if (mPreferences.contains("top-visible" + mCurrentLastVisibleSuffix)) {
       		int pos = mPreferences.getInt("top-visible" + mCurrentLastVisibleSuffix, 0);
       		setPage(pos, 0, false);        	
        } else if ((savedInstanceState != null) && (savedInstanceState.containsKey("abyss-first-visible" + mCurrentLastVisibleSuffix))) {
       		int pos = savedInstanceState.getInt("abyss-first-visible" + mCurrentLastVisibleSuffix);
       		setPage(pos, 0, false);
        } else {
        	setPage(0, 0, false);
        }    	
    }
    
    private String getQuoteSourceForFavs() {
    	if (mCurrentQuotesTable.equals(DatabaseHelper.TABLE_NAME_ABYSSBESTQUOTES))
    		return getString(R.string.favs_qs_abyssbest);
    	else 
    		return getString(R.string.favs_qs_abyssbest);
    }
    
    private void addToFavorites(String quote, String quoteSource) {
    	ContentValues values = new ContentValues();
    	values.put(DatabaseHelper.QUOTES_QUOTE, quote);
    	values.put(DatabaseHelper.QUOTES_POSTED, quoteSource);    	
    	mDb.insert(DatabaseHelper.TABLE_NAME_FAVORITES, null, values);
    	// stupid decision for getting source id for favs, should be changed to something better
    	mDb.execSQL("update " + DatabaseHelper.TABLE_NAME_FAVORITES + " set " + DatabaseHelper.QUOTES_SOURCE_ID + " = " +
    			DatabaseHelper.QUOTES_ID + " where " + DatabaseHelper.QUOTES_SOURCE_ID + " is null");
    	Toast.makeText(mContext, R.string.added_to_favs, Toast.LENGTH_SHORT).show();
    	mPreferences.edit().putInt("top-visible" + LAST_VISIBLE_SUFFIX_FAVORITES, 0).commit();
    }
	
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);
        mContext = this;
        
        mBtnPrev = (ImageButton)findViewById(R.id.btn_prev);
        mBtnNext = (ImageButton)findViewById(R.id.btn_next);        
        mTvCurrPage = (TextView)findViewById(R.id.tv_pages);
        mTvTitle = (TextView)findViewById(R.id.tv_title);        
        
        mDb = new DatabaseHelper(this).getWritableDatabase();
        
        mPreferences = PreferenceManager.getDefaultSharedPreferences(this);         
        
        mBtnPrev.setOnClickListener(new OnClickListener() {
			@Override
			public void onClick(View v) {
				if (mCurrentPage > 1)
					setPage(0, mCurrentFirstQuote, false);				
			}
		});
        
        mBtnNext.setOnClickListener(new OnClickListener() {
			@Override
			public void onClick(View v) {
				if (mCurrentQuotesOnPage > QUOTES_PER_PAGE)
					setPage(mCurrentLastQuote, 0, false);
			}
		});  
        
        getListView().setOnItemClickListener(new OnItemClickListener() {

			@Override
			public void onItemClick(AdapterView<?> arg0, View arg1, int arg2,
					long arg3) {				
				if (arg2 >= QUOTES_PER_PAGE)
					if (mCurrentQuotesOnPage > QUOTES_PER_PAGE)
						setPage(mCurrentLastQuote, 0, false);
			}
		});
        
        getListView().setOnItemLongClickListener(new OnItemLongClickListener() {

			@Override
			public boolean onItemLongClick(AdapterView<?> arg0, View arg1,
					int arg2, long arg3) {
				QuoteAdapter adapter = (QuoteAdapter)getListAdapter();
				if ((adapter == null) || (arg2 >= QUOTES_PER_PAGE))
					return false;				
				String actions[];
				if (!mCurrentQuotesTable.equals(DatabaseHelper.TABLE_NAME_FAVORITES)) {
					actions = new String[3];
				} else {
					actions = new String[2];
				}
				actions[0] = getString(R.string.long_action_copy);
				actions[1] = getString(R.string.long_action_send);
				if (!mCurrentQuotesTable.equals(DatabaseHelper.TABLE_NAME_FAVORITES)) {
					actions[2] = getString(R.string.long_action_tofavs);								
				}
				 
				AlertDialog.Builder builder = new AlertDialog.Builder(mContext);			    
				Cursor c = adapter.getCursor();
				c.moveToPosition(arg2);
				final String quote = c.getString(c.getColumnIndex(DatabaseHelper.QUOTES_QUOTE));
				final String quoteSource = String.format(getQuoteSourceForFavs(), c.getString(c.getColumnIndex(DatabaseHelper.QUOTES_SOURCE_ID)));
				builder.setAdapter(new ArrayAdapter<String>(mContext, android.R.layout.simple_dropdown_item_1line, actions),
						new AlertDialog.OnClickListener() {
							@Override
							public void onClick(DialogInterface dialog, int which) {
								switch (which) {
								case 0:
									ClipboardManager clipboard = (ClipboardManager)getSystemService(CLIPBOARD_SERVICE); 
									clipboard.setText(Html.fromHtml(quote).toString().trim());
									break;
								case 1:
									Intent sendTo = new Intent(Intent.ACTION_SEND);
									sendTo.setType("text/html");
									sendTo.putExtra(Intent.EXTRA_TEXT, quoteSource + "\n" + Html.fromHtml(quote).toString().trim());
									startActivity(Intent.createChooser(sendTo, getString(R.string.send_choose)));
									break;
								case 2:
									addToFavorites(quote, quoteSource);
									break;
								}
							}
				});
				builder.create().show(); 				
				return true;
			}
		});

        
        setQuotesTable(mPreferences.getString("quotes-type", DatabaseHelper.TABLE_NAME_ABYSSBESTQUOTES), savedInstanceState);
    }
    
    @Override
	public boolean onPrepareOptionsMenu(Menu menu) {
	    if (mCurrentQuotesTable.equals(DatabaseHelper.TABLE_NAME_ABYSSBESTQUOTES))
	    	menu.findItem(R.id.switchsource).setTitle(getString(R.string.title_favs));
	    else
	    	menu.findItem(R.id.switchsource).setTitle(getString(R.string.title_abyssbest));    	
		return true;    	
    }
    
	@Override
	public boolean onCreateOptionsMenu(Menu menu) {
	    MenuInflater inflater = getMenuInflater();
	    inflater.inflate(R.menu.menu_quotesactivity, menu);
	    return true;
	}
	
	@Override
    protected void onActivityResult(int requestCode, int resultCode, Intent data){
        switch (requestCode) {
            case 0:
                if (resultCode == RESULT_OK){
                	mTotalPages = -1;
                	if (mCurrentFirstQuote < 0)
                		mCurrentFirstQuote = 0;
                	setPage(mCurrentFirstQuote, 0, false);
                }; 
            default:
                break;
        }
    }   	

    public View getFirstVisibleView() {
        Rect r = new Rect();
        int childCount = getListView().getChildCount();
        for (int i = 0; i < childCount; ++i) {
            View listItem = getListView().getChildAt(i);
            listItem.getLocalVisibleRect(r);
            if (r.top >= 0) { // if visible
                return listItem;
            }
        }
        return null;
    }
    
	private int getTopVisibleId() {
		int pos = -1;
		View v = getFirstVisibleView();
		if (v != null) {
			pos = getListView().getPositionForView(v);
		}
		if (pos < 0)
			return mCurrentFirstQuote;
		else {
	    	Cursor c = ((QuoteAdapter)getListView().getAdapter()).getCursor(); 
	    	c.moveToPosition(pos);		
			return c.getInt(c.getColumnIndex(DatabaseHelper.QUOTES_SOURCE_ID));			
		}
	}
	
	private void saveTopVisible() {
		mPreferences.edit().putInt("top-visible" + mCurrentLastVisibleSuffix, getTopVisibleId()).commit();
	}
	
    @Override
    protected void onPause() {
        super.onPause();
        saveTopVisible();
    } 
    
    @Override
    public void onSaveInstanceState(Bundle outState) {
    	outState.putInt("abyss-first-visible" + mCurrentLastVisibleSuffix, getTopVisibleId());
    }    
	
	@Override
	public boolean onOptionsItemSelected(MenuItem item) {
	    switch (item.getItemId()) {
		    case R.id.to_first:
		    	setPage(0, 0, false);	
		        return true;
		    case R.id.to_last:
		    	setPage(0, 1, true);	
		        return true;	        
		    case R.id.update:
		    	// start activity for update
        		Intent it = new Intent(this, DownloadActivity.class);
        		startActivityForResult(it, 0);        		
		        return true;	        		        
		    case R.id.enabledisable:		    	
		    	QuoteAdapter adapter = (QuoteAdapter)getListAdapter();
		    	if (adapter != null)
		    		adapter.enableAll = !adapter.enableAll;
		        return true;	        		        		        
		    case R.id.switchsource:		    	
		    	if (mCurrentQuotesTable.equals(DatabaseHelper.TABLE_NAME_ABYSSBESTQUOTES))		    		
		    		setQuotesTable(DatabaseHelper.TABLE_NAME_FAVORITES, null);
		    	else
		    		setQuotesTable(DatabaseHelper.TABLE_NAME_ABYSSBESTQUOTES, null);
		    	mPreferences.edit().putString("quotes-type", mCurrentQuotesTable).commit();
		        return true;	        		        		        		        
		    default:
		        return super.onOptionsItemSelected(item);
	    }
	}	    
}